#include "Lexical.h"

void lexical::initLexical() {
	dict["Ident"] = "IDENFR";
	dict["IntConst"] = "INTCON";
	dict["FormatString"] = "STRCON";
	dict["main"] = "MAINTK";
	dict["const"] = "CONSTTK";
	dict["int"] = "INTTK";
	dict["break"] = "BREAKTK";
	dict["continue"] = "CONTINUETK";
	dict["if"] = "IFTK";
	dict["else"] = "ELSETK";
	dict["!"] = "NOT";
	dict["&&"] = "AND";
	dict["||"] = "OR";
	dict["while"] = "WHILETK";
	dict["getint"] = "GETINTTK";
	dict["printf"] = "PRINTFTK";
	dict["return"] = "RETURNTK";
	dict["+"] = "PLUS";
	dict["-"] = "MINU";
	dict["void"] = "VOIDTK";
	dict["*"] = "MULT";
	dict["/"] = "DIV";
	dict["%"] = "MOD";
	dict["<"] = "LSS";
	dict["<="] = "LEQ";
	dict[">"] = "GRE";
	dict[">="] = "GEQ";
	dict["=="] = "EQL";
	dict["!="] = "NEQ";
	dict["="] = "ASSIGN";
	dict[";"] = "SEMICN";
	dict[","] = "COMMA";
	dict["("] = "LPARENT";
	dict[")"] = "RPARENT";
	dict["["] = "LBRACK";
	dict["]"] = "RBRACK";
	dict["{"] = "LBRACE";
	dict["}"] = "RBRACE";
}

bool lexical::isIdent(std::string str) {
	if (!str.length()) return false;
	for (auto s : str) {
		if (!isdigit(s) && !isupper(s) && !islower(s) && s != '_') return false;
	}
	return isupper(str[0]) || islower(str[0]) || str[0] == '_';
}

bool lexical::isIdentCharacter(char c) {
	return isdigit(c) || isupper(c) || islower(c) || c == '_';
}

bool lexical::isIntConst(std::string str) {
	if (!str.length()) return false;
	for (auto s : str) {
		if (!isdigit(s)) return false;
	}
	return str[0] != '0' || str == "0";
}

bool lexical::isFormatString(std::string str) {
	return str.length() >= 2 && str[0] == '"' && str.back() == '"';
}

std::vector < std::pair < std::string, std::string> > lexical::analysis(std::vector<std::string>context) {
	bool isNote = false;
	std::vector < std::pair < std::string, std::string> > result;
	for (auto str : context) {
		int p = 0;
		std::string cur;
		while (p < str.length()) {
			while (!isNote && p < str.length() && isIdentCharacter((str[p]))) {
				cur += str[p];
				p++;
			}
			if (dict.count(cur)) {
				result.push_back({ dict[cur],cur });
				cur.clear();
			}
			else if (isIdent(cur)) {
				result.push_back({ "IDENFR",cur });
				cur.clear();
			}
			else if (isIntConst(cur)) {
				result.push_back({ "INTCON",cur });
				cur.clear();
			}
			else if (isFormatString(cur)) {
				result.push_back({ "STRCON",cur });
				cur.clear();
			}

			if (p + 1 < str.length() && str[p] == '/' && str[p + 1] == '/') {
				while (p < str.length()) {
					if (p + 1 < str.length() && str[p] == '*' && str[p + 1] == '/') isNote = false, p += 2;
					p++;
				}
			}

			if (p + 1 < str.length() && str[p] == '/' && str[p + 1] == '*') {
				isNote = true;
			}
			if (p + 1 < str.length() && str[p] == '*' && str[p + 1] == '/') {
				isNote = false;
				p += 2;
			}


			if (p < str.length() && !isNote && (!cur.empty() || str[p] != ' ' && str[p] != '\t')) cur += str[p];
			if (dict.count(cur)) {
				if (cur == "<" || cur == "=" || cur == ">" || cur == "!") {
					if (p + 1 < str.length() && str[p + 1] == '=') p++, cur += str[p];
				}
				result.push_back({ dict[cur],cur });
				cur.clear();
			}
			else if (isIntConst(cur)) {
				result.push_back({ "INTCON",cur });
				cur.clear();
			}
			else if (isFormatString(cur)) {
				result.push_back({ "STRCON",cur });
				cur.clear();
			}
			p++;
		}
	}
	return result;
}